Fix CORS/PNA, write @AppStorage defaults, switch to CGEvent, make port configurable#6
Open
michaeljstevens wants to merge 3 commits into
Open
Conversation
…t configurable Addresses weldonfisher#5. WebServer: handle OPTIONS preflight with Origin echo, Allow-Credentials, and Allow-Private-Network so the bundled browser extension can actually reach the server from modern Chrome (PNA + chrome-extension origin previously blocked every POST). Port is now read from UserDefaults, defaults to 3030 (3000 collides with most dev servers), and supports restart() for live changes. HapticMasterApp: register UserDefaults defaults on launch so non-SwiftUI reads (WebServer.processJson, NotificationWatcher) see the same defaults the @AppStorage bindings advertise. Fresh installs previously had web haptics and notification haptics silently disabled. HapticEngine: replace NSAppleScript path with CGEvent.post. AppleScript required a separate Automation permission for System Events that is often suppressed on ad-hoc signed builds (macOS 14+) due to cdhash validation failures; CGEvent uses only the already-granted Accessibility permission and is functionally equivalent for Logi Options+'s Smart Action listener. ContentView: port selection TextField in the Web Browser card. Persisted via @AppStorage("webServerPort"), validates 1024-65535, triggers WebServer.restart() on commit. build_with_icon.sh: add set -e and remove a stale "$APP_NAME.app" before building so the final mv doesn't silently fail and deploy stale artifacts. extension / extension_firefox: bump hardcoded port from 3000 to 3030 to match the new default. Configurable extension port is a possible follow-up. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reverts the default-port change to 3000 to preserve existing user expectations (matches README and historical installs). Override behavior is unchanged: change "webServerPort" via the Web Browser card when 3000 is occupied. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
popup gets a Server Port input that persists to chrome.storage.local (default 3000). popup.js uses it for the connection probe; background.js reads it from storage before each /haptic fetch. manifest host_permissions changed from "http://localhost:3000/*" to "http://localhost/*" — ports are not part of match patterns, so this matches any localhost port without needing wildcards. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Author
|
Added a follow-up commit (b6edc7b) that addresses the extension-side configurability I flagged as a follow-up in the PR description:
With this, changing the port in the app's UI now only requires opening the extension popup and entering the same port — no need to repackage the extension. Both Chrome and Firefox extensions kept in sync. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5.
Tested locally on macOS 26.3.1 with MX Master 4 + Logi Options+. After these changes, on a fresh install: direct curl POSTs vibrate the mouse, browser extension test buttons vibrate the mouse, system notifications fire haptics, and the port can be changed live from the UI.
Summary
OPTIONSpreflight with Origin echo,Allow-Credentials, andAllow-Private-Networkso the bundled browser extension can actually reach the server from modern Chrome. Port now read fromUserDefaults(default3030), supportsrestart()for live changes, and surfaces bind failures instatus.UserDefaultsdefaults on launch so non-SwiftUI reads see the same defaults the@AppStoragebindings advertise. Fixes silently-disabled web + notification haptics on fresh installs.NSAppleScriptpath withCGEvent.post. Removes the Automation→System Events permission requirement that's often suppressed on ad-hoc signed builds (macOS 14+) due to cdhash validation failures. Uses only Accessibility.TextFieldin the Web Browser card. Validates 1024–65535, triggersWebServer.restart()on commit, with a note that the browser extension must use the same port.set -e, and remove a stale"$APP_NAME.app"before building so the finalmvdoesn't silently fail and deploy stale artifacts.3000→3030to match the new default.Why these specific fixes
See #5 for the full diagnostic walkthrough — what was logged, what was sniffed, what TCC reported, etc.
Test plan
curl -X POST http://localhost:3030/haptic -d '{"pattern":"single"}'vibrates the mouse (CGEvent path + Smart Action mapping).Notes / known follow-ups
🤖 Generated with Claude Code